home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
gnu
/
emacs
/
emacs1857
/
src_d2.zoo
/
source
/
eval.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-02
|
56KB
|
2,154 lines
/* Evaluator for GNU Emacs Lisp interpreter.
Copyright (C) 1985, 1986, 1987, 1990 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "lisp.h"
#ifndef standalone
#include "commands.h"
#else
#define FROM_KBD 1
#endif
#include <setjmp.h>
/* This definition is duplicated in alloc.c and keyboard.c */
/* Putting it in lisp.h makes cc bomb out! */
struct backtrace
{
struct backtrace *next;
Lisp_Object *function;
Lisp_Object *args; /* Points to vector of args. */
int nargs; /* length of vector */
/* if nargs is UNEVALLED, args points to slot holding list of unevalled args */
char evalargs;
/* Nonzero means call value of debugger when done with this operation. */
char debug_on_exit;
};
struct backtrace *backtrace_list;
struct catchtag
{
Lisp_Object tag;
Lisp_Object val;
struct catchtag *next;
struct gcpro *gcpro;
jmp_buf jmp;
struct backtrace *backlist;
int lisp_eval_depth;
int pdlcount;
int poll_suppress_count;
};
struct catchtag *catchlist;
Lisp_Object Qautoload, Qmacro, Qexit, Qinteractive, Qcommandp, Qdefun;
Lisp_Object Vquit_flag, Vinhibit_quit, Qinhibit_quit;
Lisp_Object Qmocklisp_arguments, Vmocklisp_arguments, Qmocklisp;
Lisp_Object Qand_rest, Qand_optional;
/* Non-nil means record all fset's and provide's, to be undone
if the file being autoloaded is not fully loaded.
They are recorded by being consed onto the front of Vautoload_queue:
(FUN . ODEF) for a defun, (OFEATURES . nil) for a provide. */
Lisp_Object Vautoload_queue;
/* Current number of specbindings allocated in specpdl. */
int specpdl_size;
/* Pointer to beginning of specpdl. */
struct specbinding *specpdl;
/* Pointer to first unused element in specpdl. */
struct specbinding *specpdl_ptr;
/* Maximum size allowed for specpdl allocation */
int max_specpdl_size;
/* Depth in Lisp evaluations and function calls. */
int lisp_eval_depth;
/* Maximum allowed depth in Lisp evaluations and function calls. */
int max_lisp_eval_depth;
/* Nonzero means enter debugger before next function call */
int debug_on_next_call;
/* Nonzero means display a backtrace if an error
is handled by the command loop's error handler. */
int stack_trace_on_error;
/* Nonzero means enter debugger if an error
is handled by the command loop's error handler. */
int debug_on_error;
/* Nonzero means enter debugger if a quit signal
is handled by the command loop's error handler. */
int debug_on_quit;
Lisp_Object Vdebugger;
void specbind (), unbind_to (), record_unwind_protect ();
Lisp_Object funcall_lambda ();
extern Lisp_Object ml_apply (); /* Apply a mocklisp function to unevaluated argument list */
init_eval_once ()
{
specpdl_size = 50;
specpdl = (struct specbinding *) malloc (specpdl_size * sizeof (struct specbinding));
max_specpdl_size = 600;
max_lisp_eval_depth = 200;
}
init_eval ()
{
specpdl_ptr = specpdl;
catchlist = 0;
handlerlist = 0;
backtrace_list = 0;
Vquit_flag = Qnil;
debug_on_next_call = 0;
lisp_eval_depth = 0;
}
Lisp_Object
call_debugger (arg)
Lisp_Object arg;
{
if (lisp_eval_depth + 20 > max_lisp_eval_depth)
max_lisp_eval_depth = lisp_eval_depth + 20;
if (specpdl_size + 40 > max_specpdl_size)
max_specpdl_size = specpdl_size + 40;
debug_on_next_call = 0;
return apply1 (Vdebugger, arg);
}
do_debug_on_call (code)
Lisp_Object code;
{
debug_on_next_call = 0;
backtrace_list->debug_on_exit = 1;
call_debugger (Fcons (code, Qnil));
}
/* NOTE!!! Every function that can call EVAL must protect its args
and temporaries from garbage collection while it needs them.
The definition of `For' shows what you have to do. */
DEFUN ("or", For, Sor, 0, UNEVALLED, 0,
"Eval args until one of them yields non-NIL, then return that value.\n\
The remaining args are not evalled at all.\n\
If all args return NIL, return NIL.")
(args)
Lisp_Object args;
{
register Lisp_Object val;
Lisp_Object args_left;
struct gcpro gcpro1;
if (NULL(args))
return Qnil;
args_left = args;
GCPRO1 (args_left);
do
{
val = Feval (Fcar (args_left));
if (!NULL (val))
break;
args_left = Fcdr (args_left);
}
while (!NULL(args_left));
UNGCPRO;
return val;
}
DEFUN ("and", Fand, Sand, 0, UNEVALLED, 0,
"Eval args until one of them yields NIL, then return NIL.\n\
The remaining args are not evalled at all.\n\
If no arg yields NIL, return the last arg's value.")
(args)
Lisp_Object args;
{
register Lisp_Object val;
Lisp_Object args_left;
struct gcpro gcpro1;
if (NULL(args))
return Qt;
args_left = args;
GCPRO1 (args_left);
do
{
val = Feval (Fcar (args_left));
if (NULL (val))
break;
args_left = Fcdr (args_left);
}
while (!NULL(args_left));
UNGCPRO;
return val;
}
DEFUN ("if", Fif, Sif, 2, UNEVALLED, 0,
"(if C T E...) if C yields non-NIL do T, else do E...\n\
Returns the value of T or the value of the last of the E's.\n\
There may be no E's; then if C yields NIL, the value is NIL.")
(args)
Lisp_Object args;
{
register Lisp_Object cond;
struct gcpro gcpro1;
GCPRO1 (args);
cond = Feval (Fcar (args));
UNGCPRO;
if (!NULL (cond))
return Feval (Fcar (Fcdr (args)));
return Fprogn (Fcdr (Fcdr (args)));
}
DEFUN ("cond", Fcond, Scond, 0, UNEVALLED, 0,
"(cond CLAUSES...) tries each clause until one succeeds.\n\
Each clause looks like (C BODY...). C is evaluated\n\
and, if the value is non-nil, this clause succeeds:\n\
then the expressions in BODY are evaluated and the last one's\n\
value is the value of the cond expression.\n\
If a clause looks like (C), C's value if non-nil is returned from cond.\n\
If no clause succeeds, cond returns nil.")
(args)
Lisp_Object args;
{
register Lisp_Object clause, val;
struct gcpro gcpro1;
GCPRO1 (args);
while (!NULL (args))
{
clause = Fcar (args);
val = Feval (Fcar (clause));
if (!NULL (val))
{
if (!EQ (XCONS (clause)->cdr, Qnil))
val = Fprogn (XCONS (clause)->cdr);
break;
}
args = XCONS (args)->cdr;
}
UNGCPRO;
return val;
}
DEFUN ("progn", Fprogn, Sprogn, 0, UNEVALLED, 0,
"Eval arguments in sequence, and return the value of the last one.")
(args)
Lisp_Object args;
{
register Lisp_Object val, tem;
Lisp_Object args_left;
struct gcpro gcpro1;
/* In Mocklisp code, symbols at the front of the progn arglist
are to be bound to zero. */
if (!EQ (Vmocklisp_arguments, Qt))
{
val = make_number (0);
while (!NULL (args) && (tem = Fcar (args), XTYPE (tem) == Lisp_Symbol))
{
QUIT;
specbind (tem, val), args = Fcdr (args);
}
}
if (NULL(args))
return Qnil;
args_left = args;
GCPRO1 (args_left);
do
{
val = Feval (Fcar (args_left));
args_left = Fcdr (args_left);
}
while (!NULL(args_left));
UNGCPRO;
return val;
}
DEFUN ("prog1", Fprog1, Sprog1, 1, UNEVALLED, 0,
"Eval arguments in sequence, then return the FIRST arg's value.\n\
This value is saved during the evaluation of the remaining args,\n\
whose values are discarded.")
(args)
Lisp_Object args;
{
Lisp_Object val;
register Lisp_Object args_left;
struct gcpro gcpro1, gcpro2;
register int argnum = 0;
if (NULL(args))
return Qnil;
args_left = args;
val = Qnil;
GCPRO2 (args, val);
do
{
if (!(argnum++))
val = Feval (Fcar (args_left));
else
Feval (Fcar (args_left));